package com.wb.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ChannelHandler.Sharable
public class SimpleChatServerHandler extends ChannelHandlerAdapter {

    private final Logger logger = LoggerFactory.getLogger(SimpleChatServerHandler.class);

    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private ChannelMap<String,ChannelId> channelMap = ChannelMap.getInstance();

    private int index = 0;

    public SimpleChatServerHandler() {
        logger.info("index : {}" , ++index);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        ChannelMetadata channelMetadata = incoming.metadata();
        logger.info("channelMetadata : {}" , channelMetadata);
        for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n");
        }
        if (channels.add(ctx.channel())) {
        }
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n");
        }
        channels.remove(ctx.channel());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("client "+incoming.remoteAddress()+" 在线");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("client "+incoming.remoteAddress()+" 掉线");
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        Channel incoming = ctx.channel();
        System.out.println("client "+incoming.remoteAddress()+" 异常");
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel readChannel = ctx.channel();
        ByteBuf byteBuf = (ByteBuf)msg;
        byte[] byteArray = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(byteArray);
        String requestBody = new String(byteArray , "UTF-8");
        String byteValue = new Integer((int)byteArray[0]).toString();
        logger.info(" key : {} ,requestBody : {}  , channelMap.code : {} \n byteArray : {}" ,byteValue , requestBody , channelMap.hashCode() , byteArray);

        if (!channelMap.containsKey(byteValue)) {
            channelMap.put(byteValue , ctx.channel().id());
            logger.info(" channelMap : {} " , channelMap);
        }

        byte [] newByte = byteArray;
        byte [] headlerByte = ArrayUtils.subarray(newByte , 0 , 8);
        byte lastByte = newByte[newByte.length - 1];
        int lastValue = lastByte & 0xFF;
        logger.info("headlerByte : {} , lastByte : {} , hex: {}" , headlerByte , lastValue , Integer.toHexString(19));
        byte [] dataByteArrays = new byte[lastValue * 2 + 1];
        byte [] tempByte = null;
        for (int i = 1; i < dataByteArrays.length; i+=2) {
            tempByte = Integer.toHexString(i).getBytes();
            if (tempByte.length > 1) {
                dataByteArrays[i] = tempByte[0];
                dataByteArrays[i + 1] = tempByte[1];
            } else {
                dataByteArrays[i] = 0x00;
                dataByteArrays[i + 1] = tempByte[0];
            }
        }
        dataByteArrays[0] = (byte) ((byte)dataByteArrays.length);

        byte [] responseByteBody = new byte[headlerByte.length + dataByteArrays.length];
        for (int i = 0; i < headlerByte.length; i++) {
            responseByteBody[i] = headlerByte[i];
        }
        for (int i = 0; i < dataByteArrays.length; i++) {
            responseByteBody[i + headlerByte.length] = dataByteArrays[i];
        }
        responseByteBody[5] = (byte) (responseByteBody.length - 6);

        ByteBuf resp =  Unpooled.copiedBuffer(responseByteBody);
        logger.info("headlerByte : {} \n dataByteArrays : {} \n responseByteBody : {} \n resp : {} " ,headlerByte , dataByteArrays , responseByteBody , resp.array());
        ChannelFuture channelFuture = ctx.write(resp);
        channelFuture.addListener(new GenericFutureListener() {
            @Override
            public void operationComplete(Future future) throws Exception {
                if (future.isSuccess()) {
                    logger.info(" {}  消息发送成功!" , ctx.channel().id().toString());
                }
            }
        });

//        new Thread() {
//
//            @Override
//            public void run() {
//                while (true) {
//                    try {
//                        Thread.sleep(1000L * 1);
//                        ByteBuf resp = Unpooled.copiedBuffer(" channel thread write !".getBytes());
//                        logger.info(" thread print : {} \n String : {}" , resp , " channel thread write");
//                        ctx.writeAndFlush(resp);
//                    } catch (InterruptedException e) {
//                        logger.error("" , e);
//                    }
//                }
//            }
//        }.start();

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
}
